﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace UnityEngine.Graphics.Texture.Ijl15
{
    struct IJL_RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    unsafe struct HUFFMAN_TABLE
    {
        public int huff_class;
        public int ident;

        fixed uint huffelem[256];

        fixed ushort huffval[256];

        fixed ushort mincode[17];

        fixed short maxcode[18];

        fixed ushort valptr[17];
    }

    struct JPEGHuffTable
    {
        public System.IntPtr bits;
        public System.IntPtr vals;
        public byte hclass;
        public byte ident;
    }

    unsafe struct QUANT_TABLE
    {
        public int precision;
        public int ident;
        public System.IntPtr elements;

        fixed short elarray[84];
    }

    struct JPEGQuantTable
    {
        public System.IntPtr quantizer;

        public byte ident;
    }

    struct FRAME
    {
        public int precision;
        public int width;
        public int height;
        public int MCUheight;
        public int MCUwidth;
        public int max_hsampling;
        public int max_vsampling;
        public int ncomps;
        public int horMCU;
        public int totalMCU;

        /// FRAME_COMPONENT*
        public System.IntPtr comps;

        public int restart_interv;
        public int SeenAllDCScans;
        public int SeenAllACScans;
    }

    unsafe struct STATE
    {
        public ulong bit_buffer_64;
        public uint bit_buffer_32;
        public int bitbuf_bits_valid;

        public System.IntPtr cur_entropy_ptr;
        public System.IntPtr start_entropy_ptr;
        public System.IntPtr end_entropy_ptr;

        public int entropy_bytes_processed;
        public int entropy_buf_maxsize;
        public int entropy_bytes_left;
        public int Prog_EndOfBlock_Run;

        public System.IntPtr DIB_ptr;

        public byte unread_marker;
        public PROCESSOR_TYPE processor_type;
        public int cur_scan_comp;

        public System.IntPtr file;

        fixed byte JPGBuffer[4096];
    }

    unsafe struct JPEG_PROPERTIES
    {
        public IJLIOTYPE iotype;
        public IJL_RECT roi;
        public DCTTYPE dcttype;
        public FAST_MCU_PROCESSING_TYPE fast_processing;
        public int interrupt;

        public System.IntPtr DIBBytes;

        public int DIBWidth;
        public int DIBHeight;
        public int DIBPadBytes;
        public int DIBChannels;

        public IJL_COLOR DIBColor;
        public IJL_DIBSUBSAMPLING DIBSubsampling;
        public int DIBLineBytes;

        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
        public string JPGFile;

        public System.IntPtr JPGBytes;

        public int JPGSizeBytes;
        public int JPGWidth;
        public int JPGHeight;

        public int JPGChannels;
        public IJL_COLOR JPGColor;
        public IJL_DIBSUBSAMPLING JPGSubsampling;
        public int JPGThumbWidth;
        public int JPGThumbHeight;

        public int cconversion_reqd;
        public int upsampling_reqd;
        public int jquality;
        public int jinterleaveType;
        public int numxMCUs;
        public int numyMCUs;

        public int nqtables;
        public int maxquantindex;
        public int nhuffActables;
        public int nhuffDctables;
        public int maxhuffindex;

        /// QUANT_TABLE[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public QUANT_TABLE[] jFmtQuant;

        /// HUFFMAN_TABLE[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public HUFFMAN_TABLE[] jFmtAcHuffman;

        /// HUFFMAN_TABLE[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public HUFFMAN_TABLE[] jFmtDcHuffman;

        /// short*[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.SysUInt)]
        public System.IntPtr[] jEncFmtQuant;

        /// HUFFMAN_TABLE*[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.SysUInt)]
        public System.IntPtr[] jEncFmtAcHuffman;

        /// HUFFMAN_TABLE*[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.SysUInt)]
        public System.IntPtr[] jEncFmtDcHuffman;

        public int use_external_qtables;
        public int use_external_htables;

        /// JPEGQuantTable[4]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Struct)]
        public JPEGQuantTable[] rawquanttables;

        /// JPEGHuffTable[8]
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.Struct)]
        public JPEGHuffTable[] rawhufftables;

        fixed byte HuffIdentifierAC[4];

        fixed byte HuffIdentifierDC[4];

        public FRAME jframe;
        public int needframe;

        /// SCAN*
        public System.IntPtr jscan;

        public STATE state;
        public int SawAdobeMarker;
        public int AdobeXform;
        public System.IntPtr rowoffsets;

        /// unsigned char*
        public System.IntPtr MCUBuf;

        fixed byte tMCUBuf[720 * 2];

        public PROCESSOR_TYPE processor_type;

        /// RAW_DATA_TYPES_STATE*
        public System.IntPtr raw_coefs;

        public int progressive_found;

        /// short*
        public System.IntPtr coef_buffer;

        public UPSAMPLING_TYPE upsampling_type;

        /// SAMPLING_STATE*
        public System.IntPtr sampling_state_ptr;

        public ushort AdobeVersion;
        public ushort AdobeFlags0;
        public ushort AdobeFlags1;

        public int jfif_app0_detected;
        public ushort jfif_app0_version;
        public byte jfif_app0_units;
        public ushort jfif_app0_Xdensity;
        public ushort jfif_app0_Ydensity;

        /// char*
        public System.IntPtr jpeg_comment;
        public ushort jpeg_comment_size;
    }

    struct JPEG_CORE_PROPERTIES
    {
        public int UseJPEGPROPERTIES;

        /// unsigned char*
        public System.IntPtr DIBBytes;

        public int DIBWidth;
        public int DIBHeight;
        public int DIBPadBytes;
        public int DIBChannels;

        public IJL_COLOR DIBColor;
        public IJL_DIBSUBSAMPLING DIBSubsampling;

        /// char*
        public IntPtr JPGFile;

        /// unsigned char*
        public IntPtr JPGBytes;

        public int JPGSizeBytes;
        public int JPGWidth;
        public int JPGHeight;
        public int JPGChannels;
        public IJL_COLOR JPGColor;
        public IJL_DIBSUBSAMPLING JPGSubsampling;
        public int JPGThumbWidth;
        public int JPGThumbHeight;
        public int cconversion_reqd;
        public int upsampling_reqd;
        public int jquality;
        public JPEG_PROPERTIES jprops;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct BITMAPFILEHEADER
    {
        public UInt16 bfType;
        public UInt32 bfSize;
        public UInt16 bfReserved1;
        public UInt16 bfReserved2;
        public UInt32 bfOffBits;
    };

    struct BITMAPINFOHEADER
    {
        public uint biSize;
        public int biWidth;
        public int biHeight;
        public ushort biPlanes;
        public ushort biBitCount;
        public uint biCompression;
        public uint biSizeImage;
        public int biXPelsPerMeter;
        public int biYPelsPerMeter;
        public uint biClrUsed;
        public uint biClrImportant;

        /// <summary>
        /// call this first, before pass it to unmanaged code
        /// </summary>
        public void Init()
        {
            biSize = (uint)Marshal.SizeOf(this);
        }
    }
}
